/*
    Wild Flamenco metronome 0.1
    -
    By David Reguera Garcia - Dreg@fr33project.org -
    http://wildflamenco.blogspot.com/

    Copyright (C) <2011>  <David Reguera Garcia>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

*/

#include <windows.h>
#include "resource.h"


#define MAX_BPM_ALLOWED 600
#define DEFAULT_BPM_STR "180"
#define DEFAULT_BPM atoi( DEFAULT_BPM_STR )

#define ConvertBPMToMS( bpm ) ( (double) 60000 / bpm )

LPSTR golpe; 
LPSTR silencio;
LPSTR palma;

typedef struct PATTERN_s
{
    LPSTR * resource_array;
    unsigned int nr_elements;
    unsigned int ct;    

} PATTERN_t;

PATTERN_t pattern;

void CALLBACK TimeProc( UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 )
{     
    if ( pattern.resource_array[pattern.ct % pattern.nr_elements] != NULL )
        PlaySoundA( pattern.resource_array[pattern.ct % pattern.nr_elements], NULL, SND_MEMORY | SND_SYNC | SND_NODEFAULT );
    pattern.ct++; 
}


void FixBPM( HWND hDlg, unsigned int * bpm )
{
    SetDlgItemTextA(hDlg,IDC_EDIT1,DEFAULT_BPM_STR);
    * bpm = DEFAULT_BPM;
}

BOOL GetTheResource(LPSTR lpName, LPSTR * lpRes ) 
{ 
    BOOL bRtn; 
    HANDLE hResInfo, hRes; 
    HINSTANCE hInst;

    hInst = GetModuleHandle( NULL );

    // Find the WAVE resource. 
    hResInfo = FindResourceA(hInst, lpName, "WAVE"); 
    if (hResInfo == NULL) 
        return FALSE; 

    // Load the WAVE resource. 
 
    hRes = LoadResource(hInst, hResInfo); 
    if (hRes == NULL) 
        return FALSE; 
 
    // Lock the WAVE resource and play it. 
 
    * lpRes = LockResource(hRes); 
    if (* lpRes != NULL) { 

//        UnlockResource(hRes); 
    } 
    else 
        bRtn = 0; 
 
    // Free the WAVE resource and return success or failure. 
 
   // FreeResource(hRes); 
    return bRtn; 
} 

typedef enum flag_palos_e { 
    BULERIA_FLAG,
    SOLEA_FLAG,
    SIGUIRIYAS_FLAG,
    ALEGRIAS_FLAG,
    FANDANGOS_FLAG
} flag_palos_t;

void CreatePattern12( int flag )
{
    int i;
    i = 0;

    if ( pattern.resource_array != NULL )
        free( pattern.resource_array );

    switch ( flag )
    {
        case FANDANGOS_FLAG:
        case BULERIA_FLAG:
            pattern.ct = 0;
        break;

        case ALEGRIAS_FLAG:
        case SOLEA_FLAG:
            pattern.ct = 1;
        break;

        case SIGUIRIYAS_FLAG:
            pattern.ct = 6;
        break;
    }
           
    pattern.nr_elements = 12;
    pattern.resource_array = calloc( 1, sizeof( LPSTR ) * 12 );

    pattern.resource_array[i++] = golpe;
    pattern.resource_array[i++] = palma;
    pattern.resource_array[i++] = palma;

    pattern.resource_array[i++] = golpe;
    pattern.resource_array[i++] = palma;
    pattern.resource_array[i++] = palma;

    if ( flag == FANDANGOS_FLAG )
    {
        pattern.resource_array[i++] = golpe;
        pattern.resource_array[i++] = palma;
        pattern.resource_array[i++] = palma;
    
        pattern.resource_array[i++] = golpe;
        pattern.resource_array[i++] = palma;
        pattern.resource_array[i++] = palma;
    }
    else
    {
        pattern.resource_array[i++] = golpe;
        pattern.resource_array[i++] = palma;
    
        pattern.resource_array[i++] = golpe;
        pattern.resource_array[i++] = palma;
    
        pattern.resource_array[i++] = golpe;
        pattern.resource_array[i++] = palma;
    }
}

void CreatePatternTangoRumba( void )
{
    int i;
    i = 0;

    if ( pattern.resource_array != NULL )
        free( pattern.resource_array );

    pattern.ct = 0;
        
    pattern.nr_elements = 4;
    pattern.resource_array = calloc( 1, sizeof( LPSTR ) * 4 );

    pattern.resource_array[i++] = NULL;
    pattern.resource_array[i++] = palma;
    pattern.resource_array[i++] = palma;
    pattern.resource_array[i++] = palma;
}


BOOL CALLBACK AppDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    char bpm_str[100];
    unsigned int bpm;
    double ms;
    static MMRESULT timer_id = 0;
    TIMECAPS tc;
    static UINT resolution = 0;
    int i;

    memset( bpm_str, 0, sizeof( bpm_str ) );

  switch(uMsg)
  {
  case WM_INITDIALOG:
    SetClassLongPtr(hDlg, GCLP_HICON, (long)LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE(IDI_ICON1)));
    SetDlgItemTextA(hDlg,IDC_EDIT1,DEFAULT_BPM_STR);
    SendMessage(GetDlgItem(hDlg, IDC_RADIO1), BM_SETCHECK, TRUE, 0);

    return 1;
  case WM_COMMAND:
    switch(wParam)
    {
    case IDC_BUTTON1:
        ShellExecute(NULL, "open", "http://wildflamenco.blogspot.com/", NULL, NULL, SW_SHOWNORMAL);
    break;
    case IDSTARTT:
        if ( timer_id )
            timeKillEvent( timer_id );
        
        if ( resolution )
        {
            timeEndPeriod( resolution );
            Sleep( 400 );
        }

        if ( GetWindowTextA( GetDlgItem(hDlg, IDC_EDIT1), bpm_str, sizeof(bpm_str) - 1) == 0 )
            FixBPM( hDlg, & bpm );
        else
        {
            bpm = atoi( bpm_str );
            if ( bpm >= MAX_BPM_ALLOWED )
                FixBPM( hDlg, & bpm );
        }

        GetTheResource( "golpe", & golpe  );
        GetTheResource( "silencio", & silencio  );
        GetTheResource( "palma", & palma  );

        if(SendMessage(GetDlgItem(hDlg,IDC_RADIO1), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED)
            CreatePattern12( BULERIA_FLAG );

        if(SendMessage(GetDlgItem(hDlg,IDC_RADIO2), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED)
            CreatePattern12( SOLEA_FLAG );

        if(SendMessage(GetDlgItem(hDlg,IDC_RADIO3), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED || SendMessage(GetDlgItem(hDlg,IDC_RADIO7), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED )
            CreatePatternTangoRumba();

        if( SendMessage(GetDlgItem(hDlg,IDC_RADIO5), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED )
            CreatePattern12( SIGUIRIYAS_FLAG );

        if(SendMessage(GetDlgItem(hDlg,IDC_RADIO4), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED)
            CreatePattern12( ALEGRIAS_FLAG );

        if(SendMessage(GetDlgItem(hDlg,IDC_RADIO6), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED)
            CreatePattern12( FANDANGOS_FLAG );


        ms = ConvertBPMToMS( bpm );
    
        timeGetDevCaps( & tc, sizeof( TIMECAPS ) );
        resolution = tc.wPeriodMin;
    
        timeBeginPeriod( resolution );
    
        Sleep( 0 );
        timer_id = timeSetEvent( ms, resolution, TimeProc, 0, TIME_PERIODIC );


    return 0;

    case IDSTOPP:
        if ( timer_id )
            timeKillEvent( timer_id );
        
        if ( resolution )
            timeEndPeriod( resolution );
    break;

    case IDCANCEL:
        srand(time(NULL));
        int r = rand() % 100;
        // I dont want a spam overflow x)
        if ( r < 3 )
            ShellExecute(NULL, "open", "http://wildflamenco.blogspot.com/", NULL, NULL, SW_SHOWNORMAL);


       if ( timer_id )
            timeKillEvent( timer_id );
        
       if ( resolution )
            timeEndPeriod( resolution );

      EndDialog(hDlg, 0);
    }
  }
  return 0;
}


int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    DialogBoxParam( hThisInstance, MAKEINTRESOURCE( IDD_DIALOG1 ), 0, AppDlgProc, 0 );

    return 0;
}
